package com.econ.powercloud.ems.service.biz;

import com.econ.powercloud.clickhouse.dao.AnalogDataDAO;
import com.econ.powercloud.clickhouse.entity.AnalogData;
import com.econ.powercloud.ems.common.enums.ComputeModel;
import com.econ.powercloud.ems.common.enums.DayType;
import com.econ.powercloud.ems.dal.entity.EmsComputeConfig;
import com.econ.powercloud.ems.dal.entity.EmsComputeStatistics;
import com.econ.powercloud.ems.pojo.*;
import com.econ.powercloud.ems.service.dao.EmsComputeConfigDAO;
import com.econ.powercloud.ems.service.dao.EmsComputeStatisticsDAO;
import com.econ.powercloud.ems.util.TimeUtil;
import com.google.common.collect.Lists;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;

/**
 * @author jwc
 * @since 2022/11/25
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class EmsAnalysisService {
    private final AnalogDataDAO analogDataDAO;
    private final EmsComputeConfigDAO emsComputeConfigDAO;
    private final EmsComputeStatisticsDAO emsComputeStatisticsDAO;

    /**
     * 获取运行评价折线图数据
     * @return
     */
    public AnalysisTwoChartVO getOperationEvaluation(String energyStationId) {
        AnalysisTwoChartVO vo = AnalysisTwoChartVO.builder().horizontalData(Lists.newArrayList()).data(Lists.newArrayList()).build();
        EmsComputeConfig emsComputeConfig = emsComputeConfigDAO.selectOneByStationIdAndModelAndDayType(energyStationId, ComputeModel.S.getModel(), DayType.ONE_DAY.getCode());
        if (Objects.isNull(emsComputeConfig)) {
            log.warn("{}, 查询失败, ems_compute_config表没有查找到相应配置, compute_model: {}", ComputeModel.S.getDesc(), ComputeModel.S.getModel());
            return vo;
        }
        String pid = emsComputeConfig.getComputeCode();
        //横坐标时间轴的数据
        List<Long> horizontalData = Lists.newArrayList();
        List<String> dataList = Lists.newArrayList();
        for (int i = 30; i > 0 ; i--) {
            long time = System.currentTimeMillis() - (i * TimeUtil.ONE_DAY_MILLIS);
            AnalogData analogData = analogDataDAO.selectLastOneByTimeAndPid(pid, time);
            if (Objects.nonNull(analogData)) {
                horizontalData.add(time);
                dataList.add(analogData.getV());
            }
        }
        vo.setHorizontalData(horizontalData);
        vo.setData(Lists.newArrayList(ForecastChartVO.builder().name(ComputeModel.S.getDesc()).data(dataList).build()));
        return vo;
    }

    /**
     * 获取运行评价表格的数据
     * @param time
     * @return
     */
    public List<AnalysisVO> getAnalysisTableData(String energyStationId, Long time) {
        List<AnalysisVO> result = Lists.newArrayList();
        List<ComputeModel> list = Lists.newArrayList(ComputeModel.ACCOTPS, ComputeModel.SROPSDR, ComputeModel.ADCOTPS, ComputeModel.EAF, ComputeModel.EESS,
                ComputeModel.UOF, ComputeModel.RES, ComputeModel.AF, ComputeModel.RS, ComputeModel.S);
        for (ComputeModel computeModel : list) {
            AnalysisVO analysisVO = getIndexData(energyStationId, computeModel, DayType.ONE_DAY.getCode(), time);
            if (Objects.nonNull(analysisVO)) {
                result.add(analysisVO);
            }
        }
        return result;
    }

    /**
     * 获取电量指标（近30日）
     * @return
     */
    public List<AnalysisVO> getElectricity(String energyStationId){
        List<AnalysisVO> result = Lists.newArrayList();
        List<ComputeModel> list = Lists.newArrayList(ComputeModel.SPC, ComputeModel.EON, ComputeModel.EOFF, ComputeModel.UTH, ComputeModel.EAF);
        for (ComputeModel computeModel : list) {
            AnalysisVO analysisVO = getAnalysisVO(energyStationId, computeModel);
            if (Objects.nonNull(analysisVO)) {
                result.add(analysisVO);
            }
        }
        return result;
    }

    /**
     * 获取能效指标（近30日）
     * @return
     */
    public List<AnalysisVO> getEnergyEfficiency(String energyStationId){
        List<AnalysisVO> result = Lists.newArrayList();
        List<ComputeModel> list = Lists.newArrayList(ComputeModel.EESS, ComputeModel.RES, ComputeModel.RS, ComputeModel.ESU);
        for (ComputeModel computeModel : list) {
            AnalysisVO analysisVO = getAnalysisVO(energyStationId, computeModel);
            if (Objects.nonNull(analysisVO)) {
                result.add(analysisVO);
            }
        }
        return result;
    }

    /**
     * 获取可靠性指标（近30日）
     * @return
     */
    public List<AnalysisVO> getReliability(String energyStationId){
        List<AnalysisVO> result = Lists.newArrayList();
        List<ComputeModel> list = Lists.newArrayList(ComputeModel.UOF, ComputeModel.UTF, ComputeModel.SROPSDR);
        for (ComputeModel computeModel : list) {
            AnalysisVO analysisVO = getAnalysisVO(energyStationId, computeModel);
            if (Objects.nonNull(analysisVO)) {
                result.add(analysisVO);
            }
        }
        return result;
    }

    /**
     * 获取指标值
     * @param energyStationId
     * @param computeModel
     * @return
     */
    private AnalysisVO getAnalysisVO(String energyStationId, ComputeModel computeModel) {
        AnalysisVO vo = AnalysisVO.builder().name(computeModel.getDesc()).build();
        EmsComputeStatistics statistics = emsComputeStatisticsDAO.selectOneByCondition(energyStationId, computeModel.getModel());
        if (Objects.isNull(statistics)) {
            return vo;
        }
        vo.setVal(String.valueOf(statistics.getValue()));
        vo.setUnit(statistics.getUnit());
        return vo;
    }

    /**
     * 获取指标的值
     * @param computeModel 见枚举 ComputeModel
     * @param dayType 指标计算天数类型 见枚举 DayType
     * @param time 某天的时间
     * @return
     */
    private AnalysisVO getIndexData(String energyStationId, ComputeModel computeModel, Integer dayType, long time) {
        AnalysisVO vo = null;
        EmsComputeConfig emsComputeConfig = emsComputeConfigDAO.selectOneByStationIdAndModelAndDayType(energyStationId, computeModel.getModel(), dayType);
        if (Objects.isNull(emsComputeConfig)) {
            log.warn("ems_compute_config表未找到相应的配置, computeMode: {}, dayType: {}", computeModel, dayType);
            return vo;
        }
        vo = new AnalysisVO();
        vo.setName(computeModel.getDesc());
        if (computeModel == ComputeModel.ADCOTPS) {
            //取constant
            vo.setVal(emsComputeConfig.getConstant().toString());
        } else {
            String pid = emsComputeConfig.getComputeCode();
            if (StringUtils.isBlank(pid)) {
                return vo;
            }
            AnalogData analogData = analogDataDAO.selectLastOneByTimeAndPid(pid, time);
            if (Objects.isNull(analogData)) {
                return vo;
            }
            vo.setVal(analogData.getV());
        }
        return vo;
    }

}
